﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTOFrameworks;
using System.Xml;
using System.Xml.Linq;
using System.Data;
using PhysicalDataProvider;
using System.Collections;
using FooFun.DataElements.Dtos;
using FooFun.Faq.Dal;
using FooFun.Faq.Dal.Services;

namespace FAQFrameworks
{
    public class TopicManager
    {
        TopicService topicService;
        EventService eventService;
        TopicAboutUserService topicAboutService;

        ReplyIndexService replyIndexService;
        TopicIndexService topicIndexService;

        RecommendIndexService recommendIndexService;

        DEDataProvider dataProvider;

        public TopicManager()
        {
            topicService = new TopicService();
            eventService = new EventService();
            replyIndexService = new ReplyIndexService();
            topicIndexService = new TopicIndexService();
            recommendIndexService = new RecommendIndexService();
            topicAboutService = new TopicAboutUserService();

            dataProvider = new DEDataProvider();

            topicService.DataProvider = dataProvider;
            eventService.DataProvider = dataProvider;
            replyIndexService.DataProvider = dataProvider;
            topicIndexService.DataProvider = dataProvider;
            recommendIndexService.DataProvider = dataProvider;
        }

        public Guid CreateTopic
            (string topicTitle, Guid forumId, string remark)
        {
            IDataElement eventDE
                = eventService.CreateEvent(
                (int)FAQActionEnum.AddTopic,
                "插入问题",
                Guid.Empty,
                FAQContext.Current.User.AccountId,
                FAQContext.Current.ClientIP);

            Guid eventId
                = DataProviderUtil.GetGuid(eventDE["EventId"].Value);
            eventDE["TargetId"] = new ObjectDataElement(eventId);

            dataProvider.Begin();

            eventService.SaveEvent(eventDE);

            ITopicService service = topicService;
            service.CreateTopic(topicTitle, remark, eventId, forumId,
    FAQContext.Current.User.AccountId);

            service = topicIndexService;
            service.CreateTopic(topicTitle, remark, eventId, forumId,
                FAQContext.Current.User.AccountId);

            service = topicAboutService;
            service.CreateTopic(topicTitle, remark, eventId, forumId,
            FAQContext.Current.User.AccountId);

            eventDE["TargetId"] = eventDE["EventId"];

            dataProvider.End();

            return eventId;
        }

        IDataElement GetElementFromDB(IDataElement topicId)
        {
            dataProvider.Begin();

            IDataElement idDE = topicService.GetElement(topicId);

            dataProvider.End();

            return idDE;
        }

        string GetKey(IDataElement topicId)
        {
            return "Topic_" + topicId;
        }

        private string GetKey(Guid topicId)
        {
            return "Topic_" + topicId;
        }

        public IDataElement GetElement(IDataElement topicId)
        {
            if (CacheManager.Init[GetKey(topicId)] == null)
            {
                IDataElement topicDE = GetElementFromDB(topicId);

                CacheManager.Init[GetKey(topicId)] = topicDE;

                return topicDE;
            }

            return CacheManager.Init[GetKey(topicId)] as IDataElement;
        }

        public IDataElement GetElement(Guid topicId)
        {
            return this.GetElement(new ObjectDataElement(topicId));
        }
        /*
                public List<Topic> ListAllTopic(int forumId)
                {
                    List<Topic> list = new List<Topic>();

                    DataTable table = DataService.FillTable("SELECT * FROM t_Topics WHERE ForumId = " + forumId);

                    foreach (DataRow row in table.Rows)
                    {
                        Topic topic = new Topic(row);

                        list.Add(topic);
                    }

                    return list;
                }
        */
        public void AddReply(string reply)
        {
            IDataElement topic = this.GetElement
                (FAQContext.Current.TopicId);

            IDataElement eventDE = eventService.CreateEvent(
                (int)FAQActionEnum.AddReply, "插入回复",
                DataProviderUtil.GetGuid(topic["@TopicId"].Value),
                FAQContext.Current.User.AccountId,
                FAQContext.Current.ClientIP);

            dataProvider.Begin();

            replyIndexService.InsertIndex(
                DataProviderUtil.GetGuid(topic["@TopicId"].Value),
                FAQContext.Current.User.AccountId,
                DateTime.Now,
                DataProviderUtil.GetGuid(topic["@ForumId"].Value)
                );

            eventService.SaveEvent(eventDE);

            Guid eventId = DataProviderUtil.GetGuid(eventDE["EventId"].Value);
            Guid userId = FAQContext.Current.User.AccountId;

            IReplyService service = topicService;
            service.AddReply(topic, eventId, userId, reply);

            service = topicIndexService;
            service.AddReply(topic, eventId, userId, reply);

            service = topicAboutService;
            service.AddReply(topic, eventId, userId, reply);

            dataProvider.Begin();
        }

        public void AddRemark(string remark)
        {
            IDataElement topic = this.GetElement
                (FAQContext.Current.TopicId);

            IDataElement eventDE = eventService.CreateEvent(
                (int)FAQActionEnum.AddRemark, "插入补充说明",
                DataProviderUtil.GetGuid(topic["@TopicId"].Value),
                FAQContext.Current.User.AccountId,
                FAQContext.Current.ClientIP);

            dataProvider.Begin();

            eventService.SaveEvent(eventDE);

            topicService.AddRemark(topic, remark,
                (Guid)(eventDE["EventId"].Value));

            dataProvider.End();
        }

        public void AddConclusion
            (Guid topicId, Guid replyId, string conclusion)
        {
            IDataElement topic = this.GetElement
               (topicId);

            IDataElement eventDE = eventService.CreateEvent(
                (int)FAQActionEnum.AddConclusion, "问题结论",
                DataProviderUtil.GetGuid(topic["@TopicId"].Value),
                FAQContext.Current.User.AccountId,
                FAQContext.Current.ClientIP);

            dataProvider.Begin();

            Guid eventId = DataProviderUtil.GetGuid(
                eventDE["EventId"].Value);

            eventService.SaveEvent(eventDE);

            IReplyService service = topicService;
            service.Conclude(topic, eventId, replyId, conclusion);

            service = topicIndexService;
            service.Conclude(topic, eventId, replyId, conclusion);

            dataProvider.End();
        }

        /*
        public IDataElement ListTopic(int pageIndex, int forumId)
        {
            int pageSize = 50;

            int startIndex = pageIndex * pageSize;

            int endIndex = pageSize * (pageIndex + 1);

            DataTable table = DataService.FillTable("SELECT * FROM t_Topics WHERE ForumId = " + forumId
                + " AND TopicId BETWEEN " + startIndex + " AND "
                + endIndex);

            return new DataTableDataElement(table);
        }

        public IDataElement ListTopicPage
         (int forumId, int pageIndex, int pageSize)
        {
            string sql;
            if (pageIndex == 0)
            {
                sql = @"SELECT TOP {0} * FROM t_Topics
WHERE ForumId = {1} ORDER BY TopicId DESC";
                sql = string.Format(sql, pageSize, forumId);
            }
            else
            {
                sql = @"SELECT TOP {0} * FROM t_Topics
WHERE TopicId NOT IN(SELECT TOP {1} TopicId FROM t_Topics 
WHERE ForumId = {2} ORDER BY TopicId DESC)
AND ForumId = {2} ORDER BY TopicId DESC";

                sql = string.Format
                    (sql, pageSize, pageIndex * pageSize, forumId);

            }
            DataTable table = DataService.FillTable(sql);

            return new DataTableDataElement(table);
        }
        */
        public IDataElement ListTopicHasAnswer
            (Guid forumId, int pageIndex, int pageSize)
        {
            IDataElement dbDE
                = topicIndexService.ListTopicHasAnswer
                (forumId, pageIndex, pageSize);

            return new TopicIndexDataElement(dbDE);
        }

        public IDataElement ListTopicNoAnswer
            (Guid forumId, int pageIndex, int pageSize)
        {
            IDataElement dbDE
                = topicIndexService.ListTopicNoAnswer
                (forumId, pageIndex, pageSize);

            TopicIndexDataElement de
                = new TopicIndexDataElement(dbDE);

            return de;
        }

        public int CountForumTopic(Guid forumId, TopicStatus status)
        {
            string sql = @"SELECT COUNT(*) FROM t_TopicIndex
WHERE ForumId = '" + DataProviderUtil.GetGuidBase64(forumId) + "' AND Status=" + (int)status;

            DataTable dt = DataService.FillTable(sql);

            return (int)dt.Rows[0][0];
        }

        public IDataElement ListTopicOfUser(Guid accountId,
            int pageSize, int pageIndex)
        {
            dataProvider.Begin();

            IDataElement dbDE = topicIndexService.ListTopicOfUser(accountId, pageSize, pageIndex);

            dataProvider.End();

            TopicIndexDataElement de
                = new TopicIndexDataElement(dbDE);

            return de;
        }

        public IDataElement ListReplyOfUser(Guid accountId, int pageSize, int pageIndex)
        {
            dataProvider.Begin();

            IDataElement dbDE
                = topicIndexService.ListAnswerOfUser
                (accountId, pageSize, pageIndex);

            dataProvider.End();

            TopicIndexDataElement de
                = new TopicIndexDataElement(dbDE);

            return de;
        }

        public IDataElement ListTopicOfForum(Guid forumId, int pageSize, int pageIndex)
        {
            dataProvider.Begin();

            IDataElement dbDE = topicIndexService.ListTopicOfForum(forumId, pageSize, pageIndex);

            dataProvider.End();

            TopicIndexDataElement de
    = new TopicIndexDataElement(dbDE);

            return de;
        }

        public IDataElement ListReplyOfForum(Guid forumId, int pageSize, int pageIndex)
        {
            dataProvider.Begin();

            IDataElement dbDE = topicIndexService.ListReplyOfForum(forumId, pageSize, pageIndex);

            dataProvider.End();

            TopicIndexDataElement de
= new TopicIndexDataElement(dbDE);

            return de;
        }

        public IDataElement ListLastTopic(int pageIndex, int pageSize)
        {
            dataProvider.Begin();

            IDataElement de = topicIndexService.ListLastTopic(pageSize, pageIndex);

            dataProvider.End();

            return new TopicIndexDataElement(de);
        }

        public IDataElement ListLastReply(int pageIndex, int pageSize)
        {
            dataProvider.Begin();

            IDataElement de = topicIndexService.ListLastReply(pageSize, pageIndex);

            dataProvider.End();

            return new TopicIndexDataElement(de);
        }

        public IDataElement ListRecommends(Guid forumId)
        {
            dataProvider.Begin();

            IDataElement de =
                recommendIndexService.ListRecommends(forumId);

            dataProvider.End();

            return new TopicIndexDataElement(de);
        }

        public IDataElement ListEventAboutCreater(Guid userId, DateTime time)
        {
            TopicAboutUserService service = new TopicAboutUserService();
            IDataElement de = service.ListEventAboutCreater(userId, time);

            return de;
        }

        public IDataElement ListEventAboutReplyer(Guid userId, DateTime time)
        {
            TopicAboutUserService service = new TopicAboutUserService();
            IDataElement de = service.ListEventAboutReplyer(userId, time);

            return de;
        }

        public void MoveTopic(Guid topicId, Guid forumId)
        {
            dataProvider.Begin();

            IDataElement de = this.GetElement(topicId);

            ITopicService service = topicService;
            service.MoveTopic(de, forumId);

            service = replyIndexService;
            service.MoveTopic(de, forumId);

            service = topicIndexService;
            service.MoveTopic(de, forumId);

            service = recommendIndexService;
            service.MoveTopic(de, forumId);

            dataProvider.End();
        }

        public void RemoveTopic(Guid topicId)
        {
            dataProvider.Begin();

            ITopicService service = topicService;
            service.RemoveTopic(topicId);

            service = replyIndexService;
            service.RemoveTopic(topicId);

            service = topicIndexService;
            service.RemoveTopic(topicId);

            service = recommendIndexService;
            service.RemoveTopic(topicId);

            CacheManager.Init.Remove(GetKey(topicId));

            dataProvider.End();
        }

        public void RemoveFixTopic(Guid topicId)
        {
            dataProvider.Begin();

            recommendIndexService.RemoveFixTopic(topicId);

            dataProvider.End();
        }

        public IDataElement CountAllTopic()
        {
            dataProvider.Begin();

            int result = topicIndexService.CountAllTopic();

            dataProvider.End();

            return new IntDataElement(result);
        }

        public IDataElement CountSealedTopic()
        {
            dataProvider.Begin();

            int result = topicIndexService.CountSealedTopic();

            dataProvider.End();

            return new IntDataElement(result);
        }

        public int CountRelpyForUser(Guid userId)
        {
            return topicService.CountRelpyForUser(userId);
        }

        public int CountTopReplyForUser(Guid userId)
        {
            return topicService.CountTopReplyForUser(userId);
        }
    }

    public class TopicIndexDataElement : CustomDataElement
    {
        public TopicIndexDataElement(IDataElement de)
            : base(de)
        {

        }

        TopicManager topicManager = new TopicManager();

        public override IEnumerator GetEnumerator()
        {
            foreach (IDataElement item in this.InnerDataElement)
            {
                yield return
                    topicManager.GetElement(item["TopicId"]);
            }
        }
    }

}
